package com.bwie.community.util;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.internal.Mimetypes;
import com.aliyun.oss.model.*;
import com.bwie.common.result.PageResult;
import com.bwie.common.result.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;

@Component
public class AliOSSUtils {
    @Autowired
    private AliOSSProperties aliOSSProperties;


    /**
     * 实现上传图片到oSS 普通上传
     * @param multipartFile
     * @return
     * @throws IOException
     */
    public String upload(MultipartFile multipartFile) throws IOException {
        InputStream inputStream = multipartFile.getInputStream();
        String fileName = LocalDateTime.now().format(
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
                + multipartFile
                .getOriginalFilename();
//        上传文件到oss
        OSS ossClient = new OSSClientBuilder().build(aliOSSProperties.getEndPoint(),aliOSSProperties.getAccessKeyId(), aliOSSProperties.getAccessKeySecret());
        String url = "https://" + aliOSSProperties.getBucketName() + "." + aliOSSProperties.getEndPoint() + "/" + fileName;
        // 创建PutObjectRequest对象。
        PutObjectRequest putObjectRequest = new PutObjectRequest(aliOSSProperties.getBucketName(), fileName, inputStream);
        // 创建PutObject请求。
        PutObjectResult result = ossClient.putObject(putObjectRequest);
        return url;

    }

    /**
     * 断点续传
     * @param file
     * @return
     * @throws IOException
     */
    public String uploadBreakpoint(MultipartFile file) throws IOException {

//        创建OOSClient实例
            OSS oss = new OSSClientBuilder().build(aliOSSProperties.getEndPoint(), aliOSSProperties.getAccessKeyId(), aliOSSProperties.getAccessKeySecret());
//        创建一个临时文件
            File tempFile = File.createTempFile("oos-Breakpoint", ".tmp");

            file.transferTo(tempFile);

//        生成上传文件的文件名
            String fileName = LocalDateTime.now().format(
                    DateTimeFormatter.ofPattern("yyyy-MM-dd-HH:mm:ss"))
                    + "-" + file.getOriginalFilename();
//            创建UploadFileRequest 对象
        UploadFileRequest uploadFileRequest = new UploadFileRequest(aliOSSProperties.getBucketName(), fileName);
//        配置 上传的本地文件
        uploadFileRequest.setUploadFile(tempFile.getAbsolutePath());
//        设置并发线程数 默认1
        uploadFileRequest.setTaskNum(5);
//        设置分片大小
        uploadFileRequest.setPartSize(1024 * 1024);
//        开启断点续传模式
        uploadFileRequest.setEnableCheckpoint(true);

//        断点续传上传
        try {
            oss.uploadFile(uploadFileRequest);
            return "https://"+ aliOSSProperties.getBucketName()+"."+aliOSSProperties.getEndPoint()+ "/"+fileName;
        } catch (OSSException e) {
            System.out.println(" Error Message"+e.getErrorMessage());
            System.out.println(" Error Code"+ e.getErrorCode());
            System.out.println(" Request ID"+e.getRequestId());
            System.out.println(" Host ID"+e.getHostId());
        } catch (Throwable ce){
            System.out.println(" Error Message"+ ce.getMessage());
        }finally {
            if(oss!=null){
                oss.shutdown();
            }
        }
        return null;

    }

    /*
    *
    * 分片上传
    * */
    public String Multipart(MultipartFile file) throws IOException {

        String fileName = LocalDateTime.now().format(
                DateTimeFormatter.ofPattern("yyyy-MM-dd-HH:mm:ss"))
                + "-" + file.getOriginalFilename();
//        填写Object完整路径
//        待上传本地路径
        File tempFile = File.createTempFile("oss-multipart-", ".tmp");
        file.transferTo(tempFile);
//        创建OSSClient 实例
        OSS oss = new OSSClientBuilder().build(aliOSSProperties.getEndPoint(), aliOSSProperties.getAccessKeyId(), aliOSSProperties.getAccessKeySecret());
//        创建InitiateMultipartUploadRequest对象
        InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(aliOSSProperties.getBucketName(), fileName);
//        如果需要在初始化分片时设置请求头
        ObjectMetadata objectMetadata = new ObjectMetadata();
//        根据文件自动设置ContentType ,如果不设置，ContentType为默认值
        if(objectMetadata.getContentType()!=null){
            objectMetadata.setContentType(Mimetypes.getInstance().getMimetype(tempFile,fileName));
        }
//        初始化分片
        InitiateMultipartUploadResult uploadResult = oss.initiateMultipartUpload(initiateMultipartUploadRequest);
//        返回uploadId
        String uploadId = uploadResult.getUploadId();
//        partETage的集合
        ArrayList<PartETag> partETags = new ArrayList<>();
//        每个分片的大小
        final long partSize=1024 * 1024L;
//        根据上传的数据大小计算分片数，以File.length()获取上传数据的大小
        final File sampleFile = new File(tempFile.getAbsolutePath());
        long FileLength = sampleFile.length();
        int partCont = (int) (FileLength / partSize);
        if(FileLength % partSize!=0){
            partCont++;
        }
//        遍历 分片上传
        for (int i = 0; i < partCont; i++) {
            long startPos=i * partSize;
            long PartSize = (i + 1 == partCont) ? (FileLength -startPos) : partSize;
            UploadPartRequest uploadPartRequest = new UploadPartRequest();
            uploadPartRequest.setBucketName(aliOSSProperties.getBucketName());
            uploadPartRequest.setKey(fileName);
            uploadPartRequest.setUploadId(uploadId);
//            设置上传的分片流
            InputStream inputStream = new FileInputStream(sampleFile);
            inputStream.skip(startPos);
            uploadPartRequest.setInputStream(inputStream);
//            设置分片号,除了最后一个分片没有大小限制，其他的分片最小为 100kb
            uploadPartRequest.setPartSize(PartSize);
// 设置分片号。每一个上传的分片都有一个分片号，取值范围是1~10000，如果超出此范围，OSS将返回InvalidArgument错误码。
            uploadPartRequest.setPartNumber(i + 1);
            // 每个分片不需要按顺序上传，甚至可以在不同客户端上传，OSS会按照分片号排序组成完整的文件。
            UploadPartResult uploadPartResult = oss.uploadPart(uploadPartRequest);
            // 每次上传分片之后，OSS的返回结果包含PartETag。PartETag将被保存在partETags中。
            partETags.add(uploadPartResult.getPartETag());
        }

        CompleteMultipartUploadRequest completeMultipartUploadRequest =
                new CompleteMultipartUploadRequest(aliOSSProperties.getBucketName(), fileName, uploadId, partETags);

        CompleteMultipartUploadResult completeMultipartUploadResult = oss.completeMultipartUpload(completeMultipartUploadRequest);
        System.out.println(completeMultipartUploadResult.getETag());

        return "https://" + aliOSSProperties.getBucketName() + "." + aliOSSProperties.getEndPoint() + "/" + fileName;
    }
}
